[Rt-commit] rt branch, ip-customfields, updated. rt-3.8.8-673-g30fc9e4

? sunnavy sunnavy at bestpractical.com
Wed Sep 15 05:46:16 EDT 2010


The branch, ip-customfields has been updated
       via  30fc9e4c71a19f158ab96e4c448e4783a402a224 (commit)
       via  572f31e9e3c539a6197369d6cb2eb4177efb724c (commit)
       via  09cedc1a370259452874bf8bb593346631791405 (commit)
       via  a86b2ff006f7739d8ea007d29d5e282fb0f2c22a (commit)
       via  04271b37a446347d0e969c420eb818d9b1180d94 (commit)
      from  e24a55bbde5802e34006044dad7f067d31f9448e (commit)

Summary of changes:
 lib/RT/ObjectCustomFieldValue_Overlay.pm  |   40 ++++-
 lib/RT/Tickets_Overlay.pm                 |   61 ++++---
 t/customfields/iprange.t                  |   67 ++------
 t/customfields/{iprange.t => iprangev6.t} |  291 +++++++++++++----------------
 4 files changed, 218 insertions(+), 241 deletions(-)
 copy t/customfields/{iprange.t => iprangev6.t} (59%)

- Log -----------------------------------------------------------------
commit 04271b37a446347d0e969c420eb818d9b1180d94
Author: sunnavy <sunnavy at bestpractical.com>
Date:   Wed Sep 15 13:13:47 2010 +0800

    tiny tweak

diff --git a/lib/RT/ObjectCustomFieldValue_Overlay.pm b/lib/RT/ObjectCustomFieldValue_Overlay.pm
index e0b356c..1a5dd0a 100644
--- a/lib/RT/ObjectCustomFieldValue_Overlay.pm
+++ b/lib/RT/ObjectCustomFieldValue_Overlay.pm
@@ -433,7 +433,7 @@ sub ParseIP {
     if ( $value =~ /^($RE{net}{IPv4})$/o ) {
         return sprintf "%03d.%03d.%03d.%03d", split /\./, $1;
     }
-    elsif ( $value =~ /^$IPv6_re$/ ) {
+    elsif ( $value =~ /^$IPv6_re$/o ) {
 
         # up_fields are before '::'
         # low_fields are after '::' but without v4

commit a86b2ff006f7739d8ea007d29d5e282fb0f2c22a
Author: sunnavy <sunnavy at bestpractical.com>
Date:   Wed Sep 15 17:05:51 2010 +0800

    tweak iprange.t

diff --git a/t/customfields/iprange.t b/t/customfields/iprange.t
index 8249ef5..52bfb2a 100644
--- a/t/customfields/iprange.t
+++ b/t/customfields/iprange.t
@@ -3,7 +3,7 @@
 use strict;
 use warnings;
 
-use RT::Test tests => 133;
+use RT::Test tests => 127;
 
 my ($baseurl, $agent) =RT::Test->started_ok;
 ok( $agent->login, 'log in' );
@@ -110,11 +110,7 @@ diag "create a ticket and edit IP field using Edit page" if $ENV{'TEST_VERBOSE'}
     my $ticket = RT::Ticket->new($RT::SystemUser);
     $ticket->Load($id);
     ok( $ticket->id, 'loaded ticket' );
-    my $values = $ticket->CustomFieldValues('IP');
-    my %has = map { $_->Content => 1 } @{ $values->ItemsArrayRef };
-    is( scalar values %has, 1, "one IP were added" );
-    ok( $has{$val}, "has value" )
-      or diag "but has values " . join ", ", keys %has;
+    is( $ticket->FirstCustomFieldValue('IP'), $val, 'correct value' );
 
     diag "set IP with spaces around" if $ENV{'TEST_VERBOSE'};
     $val = "  172.16.0.2  \n  ";
@@ -131,11 +127,7 @@ diag "create a ticket and edit IP field using Edit page" if $ENV{'TEST_VERBOSE'}
     $ticket = RT::Ticket->new($RT::SystemUser);
     $ticket->Load($id);
     ok( $ticket->id, 'loaded ticket' );
-    $values = $ticket->CustomFieldValues('IP');
-    %has = map { $_->Content => 1 } @{ $values->ItemsArrayRef };
-    is( scalar values %has, 1, "one IP were added" );
-    ok( $has{'172.16.0.2'}, "has value" )
-      or diag "but has values " . join ", ", keys %has;
+    is( $ticket->FirstCustomFieldValue('IP'), '172.16.0.2', 'correct value' );
 
     diag "replace IP with a range" if $ENV{'TEST_VERBOSE'};
     $val = '172.16.0.0-172.16.0.255';
@@ -152,22 +144,15 @@ diag "create a ticket and edit IP field using Edit page" if $ENV{'TEST_VERBOSE'}
     $ticket = RT::Ticket->new($RT::SystemUser);
     $ticket->Load($id);
     ok( $ticket->id, 'loaded ticket' );
-    $values = $ticket->CustomFieldValues('IP');
-    %has = map { $_->Content => 1 } @{ $values->ItemsArrayRef };
-    is( scalar values %has, 1, "one IP were added" );
-    ok( $has{$val}, "has value" )
-      or diag "but has values " . join ", ", keys %has;
+    is( $ticket->FirstCustomFieldValue('IP'), $val, 'correct value' );
 
     diag "delete range, add another range using CIDR" if $ENV{'TEST_VERBOSE'};
     $val = '172.16/16';
     $agent->follow_link_ok( { text => 'Basics', n => "1" },
         "Followed 'Basics' link" );
     $agent->form_number(3);
-    like(
-        $agent->value($cf_field),
-        qr/^\s*\Q172.16.0.0-172.16.0.255\E\s*$/,
-        'IP is empty'
-    );
+    is( $agent->value($cf_field),
+        '172.16.0.0-172.16.0.255', 'IP is in input box' );
     $agent->field( $cf_field => $val );
     $agent->click('SubmitTicket');
 
@@ -176,11 +161,8 @@ diag "create a ticket and edit IP field using Edit page" if $ENV{'TEST_VERBOSE'}
     $ticket = RT::Ticket->new($RT::SystemUser);
     $ticket->Load($id);
     ok( $ticket->id, 'loaded ticket' );
-    $values = $ticket->CustomFieldValues('IP');
-    %has = map { $_->Content => 1 } @{ $values->ItemsArrayRef };
-    is( scalar values %has, 1, "one IP were added" );
-    ok( $has{'172.16.0.0-172.16.255.255'}, "has value" )
-      or diag "but has values " . join ", ", keys %has;
+    is( $ticket->FirstCustomFieldValue('IP'),
+        '172.16.0.0-172.16.255.255', 'correct value' );
 }
 
 diag "check that we parse correct IPs only" if $ENV{'TEST_VERBOSE'};
@@ -203,11 +185,7 @@ diag "check that we parse correct IPs only" if $ENV{'TEST_VERBOSE'};
         $ticket->Load($id);
         is( $ticket->id, $id, 'loaded ticket' );
 
-        my %has = ();
-        $has{ $_->Content }++
-          foreach @{ $ticket->CustomFieldValues('IP')->ItemsArrayRef };
-        is( scalar values %has, 1, "one IP was added" );
-        ok( $has{$valid}, 'correct value' );
+        is( $ticket->FirstCustomFieldValue('IP'), $valid, 'correct value' );
     }
 
     for my $invalid (qw{255.255.255.256 355.255.255.255 8.13.8/8.13.0/1.0}) {
@@ -249,18 +227,8 @@ diag "search tickets by IP" if $ENV{'TEST_VERBOSE'};
     $tickets->FromSQL("id = $id AND CF.{IP} = '172.16.1.1'");
     ok( $tickets->Count, "found tickets" );
 
-    my $flag = 1;
-    while ( my $ticket = $tickets->Next ) {
-        my %has =
-          map { $_->Content => 1 }
-          @{ $ticket->CustomFieldValues('IP')->ItemsArrayRef };
-        next if $has{'172.16.1.0-172.16.1.1'};
-        $flag = 0;
-        ok( 0, "ticket #" . $ticket->id . " has no IP 172.16.1.1, but should" )
-          or diag "but has values " . join ", ", keys %has;
-        last;
-    }
-    ok( 1, "all tickets has IP 172.16.1.1" ) if $flag;
+    is( $ticket->FirstCustomFieldValue('IP'),
+        '172.16.1.0-172.16.1.1', 'correct value' );
 }
 
 diag "search tickets by IP range" if $ENV{'TEST_VERBOSE'};
@@ -287,15 +255,8 @@ diag "search tickets by IP range" if $ENV{'TEST_VERBOSE'};
     $tickets->FromSQL("id = $id AND CF.{IP} = '172.16.2.0-172.16.2.255'");
     ok( $tickets->Count, "found tickets" );
 
-    my $flag = 1;
-    while ( my $ticket = $tickets->Next ) {
-        my %has = map { $_->Content => 1 } @{ $ticket->CustomFieldValues('IP')->ItemsArrayRef };
-        next if grep /^172\.16\.2\./, keys %has;
-        $flag = 0;
-        ok(0, "ticket #". $ticket->id ." has no IP from 172.16.2.0-172.16.2.255, but should");
-        last;
-    }
-    ok(1, "all tickets have at least one IP from 172.16.2.0-172.16.2.255") if $flag;
+    is( $ticket->FirstCustomFieldValue('IP'),
+        '172.16.2.0-172.16.2.63', 'correct value' );
 }
 
 diag "create two tickets with different IPs and check several searches" if $ENV{'TEST_VERBOSE'};
@@ -492,7 +453,7 @@ diag "create two tickets with different IP ranges and check several searches" if
     # IP range, greater than both
     $tickets = RT::Tickets->new( $RT::SystemUser );
     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = '192.168.22/24'");
-    is( $tickets->Count, 0, "didn't finnd ticket" ) or diag "but found ". $tickets->First->id;
+    is( $tickets->Count, 0, "didn't find ticket" ) or diag "but found ". $tickets->First->id;
 }
 
 

commit 09cedc1a370259452874bf8bb593346631791405
Author: sunnavy <sunnavy at bestpractical.com>
Date:   Wed Sep 15 17:06:21 2010 +0800

    ipv6 support of iprange

diff --git a/lib/RT/ObjectCustomFieldValue_Overlay.pm b/lib/RT/ObjectCustomFieldValue_Overlay.pm
index 1a5dd0a..e42cded 100644
--- a/lib/RT/ObjectCustomFieldValue_Overlay.pm
+++ b/lib/RT/ObjectCustomFieldValue_Overlay.pm
@@ -250,7 +250,7 @@ sub Content {
 
         return $content if $self->CustomFieldObj->Type eq 'IPAddress';
 
-        my $large_content = $self->__Value('LargeContent');
+        my $large_content = $self->LargeContent;
         if ( $large_content =~ /^\s*($re_ip_serialized)\s*$/o ) {
             my $eIP = sprintf "%d.%d.%d.%d", split /\./, $1;
             if ( $content eq $eIP ) {
@@ -260,6 +260,15 @@ sub Content {
                 return $content . "-" . $eIP;
             }
         }
+        elsif ( $large_content =~ /^\s*($IPv6_re)\s*$/o ) {
+            my $eIP = $1;
+            if ( $content eq $eIP ) {
+                return $content;
+            }
+            else {
+                return $content . "-" . $eIP;
+            }
+        }
         else {
             return $content;
         }
@@ -400,24 +409,40 @@ sub IncludeContentForValue {
 
 sub ParseIPRange {
     my $self = shift;
-    my $arg = shift or return ();
+    my $value = shift or return;
+    $value = lc $value;
+    $value =~ s!^\s+!!;
+    $value =~ s!\s+$!!;
     
-    if ( $arg =~ /^\s*$RE{net}{CIDR}{IPv4}{-keep}\s*$/go ) {
+    if ( $value =~ /^$RE{net}{CIDR}{IPv4}{-keep}$/go ) {
         my $cidr = join( '.', map $_||0, (split /\./, $1)[0..3] ) ."/$2";
-        $arg = (Net::CIDR::cidr2range( $cidr ))[0] || $arg;
+        $value = (Net::CIDR::cidr2range( $cidr ))[0] || $value;
+    }
+    elsif ( $value =~ /^$IPv6_re(?:\/\d+)?$/o ) {
+        $value = (Net::CIDR::cidr2range( $value ))[0] || $value;
     }
     
     my ($sIP, $eIP);
-    if ( $arg =~ /^\s*($RE{net}{IPv4})\s*$/o ) {
+    if ( $value =~ /^($RE{net}{IPv4})$/o ) {
         $sIP = $eIP = sprintf "%03d.%03d.%03d.%03d", split /\./, $1;
     }
-    elsif ( $arg =~ /^\s*($RE{net}{IPv4})-($RE{net}{IPv4})\s*$/o ) {
+    elsif ( $value =~ /^($RE{net}{IPv4})-($RE{net}{IPv4})$/o ) {
         $sIP = sprintf "%03d.%03d.%03d.%03d", split /\./, $1;
         $eIP = sprintf "%03d.%03d.%03d.%03d", split /\./, $2;
     }
+    elsif ( $value =~ /^($IPv6_re)$/o ) {
+        $sIP = $self->ParseIP( $1 );
+        $eIP = $sIP;
+    }
+    elsif ( $value =~ /^($IPv6_re)-($IPv6_re)$/o ) {
+        ($sIP, $eIP) = ( $1, $2 );
+        $sIP = $self->ParseIP( $sIP );
+        $eIP = $self->ParseIP( $eIP );
+    }
     else {
-        return ();
+        return;
     }
+
     ($sIP, $eIP) = ($eIP, $sIP) if $sIP gt $eIP;
     
     return $sIP, $eIP;
diff --git a/lib/RT/Tickets_Overlay.pm b/lib/RT/Tickets_Overlay.pm
index 738892c..451d8d1 100755
--- a/lib/RT/Tickets_Overlay.pm
+++ b/lib/RT/Tickets_Overlay.pm
@@ -1390,17 +1390,35 @@ sub _CustomFieldLimit {
         }
     }
 
-    if (   $cf
-        && $value =~ /^\s*$RE{net}{CIDR}{IPv4}{-keep}\s*$/o )
-    {
+    if ( $cf && $cf->Type eq 'IPAddressRange' ) {
 
-        # convert incomplete 192.168/24 to 192.168.0.0/24 format
-        my $cidr =
-          join( '.', map $_ || 0, ( split /\./, $1 )[ 0 .. 3 ] ) . "/$2";
+        if ( $value =~ /^\s*$RE{net}{CIDR}{IPv4}{-keep}\s*$/o ) {
 
-        # convert to range and continue, it will be catched by next wrapper
-        $value = ( Net::CIDR::cidr2range($cidr) )[0] || $value;
+            # convert incomplete 192.168/24 to 192.168.0.0/24 format
+            $value =
+              join( '.', map $_ || 0, ( split /\./, $1 )[ 0 .. 3 ] ) . "/$2"
+              || $value;
+        }
 
+        my ( $start_ip, $end_ip ) =
+          RT::ObjectCustomFieldValue->ParseIPRange($value);
+        if ( $start_ip && $end_ip ) {
+            if ( $op =~ /^([<>])=?$/ ) {
+                my $is_less = $1 eq '<' ? 1 : 0;
+                if ( $is_less ) {
+                    $value = $start_ip;
+                }
+                else {
+                    $value = $end_ip;
+                }
+            }
+            else {
+                $value = join '-', $start_ip, $end_ip;
+            }
+        }
+        else {
+            $RT::Logger->warn("$value is not a valid IPAddressRange");
+        }
     }
 
     my $single_value = !$cf || !$cfid || $cf->SingleValue;
@@ -1432,11 +1450,7 @@ sub _CustomFieldLimit {
     }
     elsif ( $op !~ /^[<>]=?$/ && (  $cf && $cf->Type eq 'IPAddressRange')) {
     
-        $value =~ /^\s*($RE{net}{IPv4})\s*(?:-\s*($RE{net}{IPv4})\s*)?$/o;
-        my ($start_ip, $end_ip) = ($1, ($2 || $1));
-        $_ = sprintf "%03d.%03d.%03d.%03d", split /\./, $_
-            for $start_ip, $end_ip;
-        ($start_ip, $end_ip) = ($end_ip, $start_ip) if $start_ip gt $end_ip;
+        my ($start_ip, $end_ip) = split /-/, $value;
         
         $self->_OpenParen;
         if ( $op !~ /NOT|!=|<>/i ) { # positive equation
@@ -1451,16 +1465,17 @@ sub _CustomFieldLimit {
             ); 
             # as well limit borders so DB optimizers can use better
             # estimations and scan less rows
-            $self->_CustomFieldLimit(
-                $field, '>=', '000.000.000.000', %rest,
-                SUBKEY          => $rest{'SUBKEY'}. '.Content',
-                ENTRYAGGREGATOR => 'AND',
-            );
-            $self->_CustomFieldLimit(
-                $field, '<=', '255.255.255.255', %rest,
-                SUBKEY          => $rest{'SUBKEY'}. '.LargeContent',
-                ENTRYAGGREGATOR => 'AND',
-            );  
+# have to disable this tweak because of ipv6
+#            $self->_CustomFieldLimit(
+#                $field, '>=', '000.000.000.000', %rest,
+#                SUBKEY          => $rest{'SUBKEY'}. '.Content',
+#                ENTRYAGGREGATOR => 'AND',
+#            );
+#            $self->_CustomFieldLimit(
+#                $field, '<=', '255.255.255.255', %rest,
+#                SUBKEY          => $rest{'SUBKEY'}. '.LargeContent',
+#                ENTRYAGGREGATOR => 'AND',
+#            );  
         }       
         else { # negative equation
             $self->_CustomFieldLimit($field, '>', $end_ip, %rest);

commit 572f31e9e3c539a6197369d6cb2eb4177efb724c
Author: sunnavy <sunnavy at bestpractical.com>
Date:   Wed Sep 15 17:15:50 2010 +0800

    it's safe to use text/plain type for LargeContent of IP cf

diff --git a/lib/RT/ObjectCustomFieldValue_Overlay.pm b/lib/RT/ObjectCustomFieldValue_Overlay.pm
index e42cded..53d13f1 100644
--- a/lib/RT/ObjectCustomFieldValue_Overlay.pm
+++ b/lib/RT/ObjectCustomFieldValue_Overlay.pm
@@ -94,6 +94,7 @@ sub Create {
         if ($args{'Content'}) {
             ($args{'Content'}, $args{'LargeContent'}) = $self->ParseIPRange( $args{'Content'} );
         }
+        $args{'ContentType'} = 'text/plain';
 
         unless ( defined $args{'Content'} ) {
             return
@@ -250,7 +251,7 @@ sub Content {
 
         return $content if $self->CustomFieldObj->Type eq 'IPAddress';
 
-        my $large_content = $self->LargeContent;
+        my $large_content = $self->__Value('LargeContent');
         if ( $large_content =~ /^\s*($re_ip_serialized)\s*$/o ) {
             my $eIP = sprintf "%d.%d.%d.%d", split /\./, $1;
             if ( $content eq $eIP ) {

commit 30fc9e4c71a19f158ab96e4c448e4783a402a224
Author: sunnavy <sunnavy at bestpractical.com>
Date:   Wed Sep 15 17:16:11 2010 +0800

    iprangev6.t

diff --git a/t/customfields/iprangev6.t b/t/customfields/iprangev6.t
new file mode 100644
index 0000000..1af1897
--- /dev/null
+++ b/t/customfields/iprangev6.t
@@ -0,0 +1,473 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use RT::Test tests => 153;
+
+my ($baseurl, $agent) =RT::Test->started_ok;
+ok( $agent->login, 'log in' );
+
+my $q = RT::Queue->new($RT::SystemUser);
+$q->Load('General');
+my $ip_cf = RT::CustomField->new($RT::SystemUser);
+        
+my ($val,$msg) = $ip_cf->Create(Name => 'IP', Type =>'IPAddressRange', LookupType => 'RT::Queue-RT::Ticket');
+ok($val,$msg);
+my $cf_id = $val;
+$ip_cf->AddToObject($q);
+use_ok('RT');
+
+my $cf;
+diag "load and check basic properties of the IP CF" if $ENV{'TEST_VERBOSE'};
+{
+    my $cfs = RT::CustomFields->new( $RT::SystemUser );
+    $cfs->Limit( FIELD => 'Name', VALUE => 'IP' );
+    is( $cfs->Count, 1, "found one CF with name 'IP'" );
+
+    $cf = $cfs->First;
+    is( $cf->Type, 'IPAddressRange', 'type check' );
+    is( $cf->LookupType, 'RT::Queue-RT::Ticket', 'lookup type check' );
+    ok( !$cf->MaxValues, "unlimited number of values" );
+    ok( !$cf->Disabled, "not disabled" );
+}
+
+diag "check that CF applies to queue General" if $ENV{'TEST_VERBOSE'};
+{
+    my $cfs = $q->TicketCustomFields;
+    $cfs->Limit( FIELD => 'id', VALUE => $cf->id, ENTRYAGGREGATOR => 'AND' );
+    is( $cfs->Count, 1, 'field applies to queue' );
+}
+
+my %valid = (
+    'abcd:' x 7 . 'abcd' => 'abcd:' x 7 . 'abcd',
+    '034:' x 7 . '034'   => '0034:' x 7 . '0034',
+    'abcd::'             => 'abcd:' . '0000:' x 6 . '0000',
+    '::abcd'             => '0000:' x 7 . 'abcd',
+    'abcd::034'          => 'abcd:' . '0000:' x 6 . '0034',
+    'abcd::192.168.1.1'  => 'abcd:' . '0000:' x 5 . 'c0a8:0101',
+    '::192.168.1.1'      => '0000:' x 6 . 'c0a8:0101',
+);
+
+diag "create a ticket via web and set IP" if $ENV{'TEST_VERBOSE'};
+{
+    for my $ip ( keys %valid ) {
+        ok $agent->goto_create_ticket($q), "go to create ticket";
+        my $cf_field = "Object-RT::Ticket--CustomField-$cf_id-Values";
+        $agent->submit_form(
+            form_name => 'TicketCreate',
+            fields    => {
+                Subject   => 'test ip',
+                $cf_field => $ip,
+            }
+        );
+
+        $agent->content_like( qr/$valid{$ip}/, "IP on the page" );
+        my ($id) = $agent->content =~ /Ticket (\d+) created/;
+        ok( $id, "created ticket $id" );
+
+        my $ticket = RT::Ticket->new($RT::SystemUser);
+        $ticket->Load($id);
+        ok( $ticket->id, 'loaded ticket' );
+        is( $ticket->FirstCustomFieldValue('IP'), $valid{$ip},
+            'correct value' );
+    }
+}
+
+diag "create a ticket via web with CIDR" if $ENV{'TEST_VERBOSE'};
+{
+    my $val = 'abcd:034::/31';
+    ok $agent->goto_create_ticket($q), "go to create ticket";
+    my $cf_field = "Object-RT::Ticket--CustomField-$cf_id-Values";
+    $agent->submit_form(
+        form_name => 'TicketCreate',
+        fields    => {
+            Subject                                       => 'test ip',
+            $cf_field => $val,
+        }
+    );
+
+    my ($id) = $agent->content =~ /Ticket (\d+) created/;
+    ok( $id, "created ticket $id" );
+
+    my $ticket = RT::Ticket->new($RT::SystemUser);
+    $ticket->Load($id);
+    ok( $ticket->id, 'loaded ticket' );
+    is(
+        $ticket->FirstCustomFieldValue('IP'),
+'abcd:0034:0000:0000:0000:0000:0000:0000-abcd:0035:ffff:ffff:ffff:ffff:ffff:ffff',
+        'correct value'
+    );
+}
+
+diag "create a ticket and edit IP field using Edit page" if $ENV{'TEST_VERBOSE'};
+{
+    my $val = 'abcd' . ':abcd' x 7;
+    ok $agent->goto_create_ticket($q), "go to create ticket";
+    $agent->submit_form(
+        form_name => 'TicketCreate',
+        fields    => { Subject => 'test ip', }
+    );
+
+    my ($id) = $agent->content =~ /Ticket (\d+) created/;
+    ok( $id, "created ticket $id" );
+    my $cf_field = "Object-RT::Ticket-$id-CustomField-$cf_id-Values";
+
+    $agent->follow_link_ok( { text => 'Basics', n => "1" },
+        "Followed 'Basics' link" );
+    $agent->form_number(3);
+
+    is( $agent->value($cf_field), '', 'IP is empty' );
+    $agent->field( $cf_field => $val );
+    $agent->click('SubmitTicket');
+
+    $agent->content_contains( $val, "IP on the page" );
+
+    my $ticket = RT::Ticket->new($RT::SystemUser);
+    $ticket->Load($id);
+    ok( $ticket->id, 'loaded ticket' );
+    is( $ticket->FirstCustomFieldValue('IP'), $val, 'correct value' );
+
+    diag "set IP with spaces around" if $ENV{'TEST_VERBOSE'};
+    $agent->follow_link_ok( { text => 'Basics', n => "1" },
+        "Followed 'Basics' link" );
+    $agent->form_number(3);
+    is( $agent->value($cf_field), $val, 'IP is in input box' );
+    $val = 'bbcd' . ':abcd' x 7;
+    $agent->field( $cf_field => "   $val   " );
+    $agent->click('SubmitTicket');
+
+    $agent->content_contains( $val, "IP on the page" );
+
+    $ticket = RT::Ticket->new($RT::SystemUser);
+    $ticket->Load($id);
+    ok( $ticket->id, 'loaded ticket' );
+    is( $ticket->FirstCustomFieldValue('IP'), $val, 'correct value' );
+
+    diag "replace IP with a range" if $ENV{'TEST_VERBOSE'};
+    $agent->follow_link_ok( { text => 'Basics', n => "1" },
+        "Followed 'Basics' link" );
+    $agent->form_number(3);
+    is( $agent->value($cf_field), $val, 'IP is in input box' );
+    $val = 'abcd' . ':0000' x 7 . '-' . 'abcd' . ':ffff' x 7;
+    $agent->field( $cf_field => 'abcd::/16' );
+    $agent->click('SubmitTicket');
+
+    $agent->content_contains( $val, "IP on the page" );
+
+    $ticket = RT::Ticket->new($RT::SystemUser);
+    $ticket->Load($id);
+    ok( $ticket->id, 'loaded ticket' );
+    is( $ticket->FirstCustomFieldValue('IP'), $val, 'correct value' );
+
+    diag "delete range, add another range using CIDR" if $ENV{'TEST_VERBOSE'};
+    $agent->follow_link_ok( { text => 'Basics', n => "1" },
+        "Followed 'Basics' link" );
+    $agent->form_number(3);
+    is( $agent->value($cf_field), $val, 'IP is in input box' );
+    $val = 'bb00' . ':0000' x 7 . '-' . 'bbff' . ':ffff' x 7;
+    $agent->field( $cf_field => $val );
+    $agent->click('SubmitTicket');
+
+    $agent->content_contains( $val, "IP on the page" );
+
+    $ticket = RT::Ticket->new($RT::SystemUser);
+    $ticket->Load($id);
+    ok( $ticket->id, 'loaded ticket' );
+    is( $ticket->FirstCustomFieldValue('IP'), $val, 'correct value' );
+}
+
+diag "check that we parse correct IPs only" if $ENV{'TEST_VERBOSE'};
+{
+
+    my $cf_field = "Object-RT::Ticket--CustomField-$cf_id-Values";
+    my @invalid =
+      ( '::', 'abcd:', 'efgh', 'abcd:' x 8 . 'abcd', 'abcd::abcd::abcd' );
+    for my $invalid (@invalid) {
+        ok $agent->goto_create_ticket($q), "go to create ticket";
+        $agent->submit_form(
+            form_name => 'TicketCreate',
+            fields    => {
+                Subject   => 'test ip',
+                $cf_field => $invalid,
+            }
+        );
+
+        $agent->content_like( qr/can not be parsed to IPAddressRange/,
+            'ticket fails to create' );
+    }
+
+}
+
+diag "search tickets by IP" if $ENV{'TEST_VERBOSE'};
+{
+    my $val = 'abcd::/16';
+    ok $agent->goto_create_ticket($q), "go to create ticket";
+    my $cf_field = "Object-RT::Ticket--CustomField-$cf_id-Values";
+    $agent->submit_form(
+        form_name => 'TicketCreate',
+        fields    => {
+            Subject   => 'test ip',
+            $cf_field => $val,
+        }
+    );
+
+    my ($id) = $agent->content =~ /Ticket (\d+) created/;
+    ok( $id, "created ticket $id" );
+
+    my $ticket = RT::Ticket->new($RT::SystemUser);
+    $ticket->Load($id);
+    ok( $ticket->id, 'loaded ticket' );
+
+    my $tickets = RT::Tickets->new($RT::SystemUser);
+    $tickets->FromSQL("id = $id AND CF.{IP} = 'abcd::/16'");
+    ok( $tickets->Count, "found tickets" );
+    is(
+        $ticket->FirstCustomFieldValue('IP'),
+'abcd:0000:0000:0000:0000:0000:0000:0000-abcd:ffff:ffff:ffff:ffff:ffff:ffff:ffff',
+        'correct value'
+    );
+}
+
+diag "search tickets by IP range" if $ENV{'TEST_VERBOSE'};
+{
+    my $val = 'abcd:ef00::/24';
+    ok $agent->goto_create_ticket($q), "go to create ticket";
+    my $cf_field = "Object-RT::Ticket--CustomField-$cf_id-Values";
+    $agent->submit_form(
+        form_name => 'TicketCreate',
+        fields    => {
+            Subject   => 'test ip',
+            $cf_field => $val,
+        }
+    );
+
+    my ($id) = $agent->content =~ /Ticket (\d+) created/;
+    ok( $id, "created ticket $id" );
+
+    my $ticket = RT::Ticket->new($RT::SystemUser);
+    $ticket->Load($id);
+    ok( $ticket->id, 'loaded ticket' );
+
+    my $tickets = RT::Tickets->new( $RT::SystemUser );
+    $tickets->FromSQL("id = $id AND CF.{IP} =
+            'abcd:ef::-abcd:efff:ffff:ffff:ffff:ffff:ffff:ffff'");
+    ok( $tickets->Count, "found tickets" );
+
+    is(
+        $ticket->FirstCustomFieldValue('IP'),
+'abcd:ef00:0000:0000:0000:0000:0000:0000-abcd:efff:ffff:ffff:ffff:ffff:ffff:ffff',
+        'correct value'
+    );
+}
+
+diag "create two tickets with different IPs and check several searches" if $ENV{'TEST_VERBOSE'};
+{
+    ok $agent->goto_create_ticket($q), "go to create ticket";
+    my $cf_field = "Object-RT::Ticket--CustomField-$cf_id-Values";
+    my $first_ip = 'cbcd' . ':0000' x 7;
+    my $second_ip = 'cbdd' . ':0000' x 7;
+    $agent->submit_form(
+        form_name => 'TicketCreate',
+        fields    => {
+            Subject   => 'test ip',
+            $cf_field => $first_ip,
+        }
+    );
+
+    my ($id1) = $agent->content =~ /Ticket (\d+) created/;
+    ok( $id1, "created first ticket $id1" );
+
+    ok $agent->goto_create_ticket($q), "go to create ticket";
+    $agent->submit_form(
+        form_name => 'TicketCreate',
+        fields    => {
+            Subject   => 'test ip',
+            $cf_field => $second_ip,
+        }
+    );
+
+    my ($id2) = $agent->content =~ /Ticket (\d+) created/;
+    ok( $id2, "created second ticket $id2" );
+
+    my $tickets = RT::Tickets->new( $RT::SystemUser );
+    $tickets->FromSQL("id = $id1 OR id = $id2");
+    is( $tickets->Count, 2, "found both tickets by 'id = x OR y'" );
+
+    # IP
+    $tickets = RT::Tickets->new( $RT::SystemUser );
+    $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = '$first_ip'");
+    is( $tickets->Count, 1, "found one ticket" );
+    is( $tickets->First->FirstCustomFieldValue('IP'), $first_ip, "correct value" );
+    $tickets = RT::Tickets->new( $RT::SystemUser );
+    $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = '$second_ip'");
+    is( $tickets->Count, 1, "found one ticket" );
+    is( $tickets->First->FirstCustomFieldValue('IP'), $second_ip, "correct value" );
+
+    # IP/32 - one address
+    $tickets = RT::Tickets->new( $RT::SystemUser );
+    $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = 'cbcd::/16'");
+    is( $tickets->Count, 1, "found one ticket" );
+    is( $tickets->First->FirstCustomFieldValue('IP'), $first_ip, "correct value" );
+    $tickets = RT::Tickets->new( $RT::SystemUser );
+    $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = 'cbdd::/16'");
+    is( $tickets->Count, 1, "found one ticket" );
+    is( $tickets->First->FirstCustomFieldValue('IP'), $second_ip, "correct value" );
+
+    # IP range
+    $tickets = RT::Tickets->new( $RT::SystemUser );
+    $tickets->FromSQL(
+        "(id = $id1 OR id = $id2) AND CF.{IP} = '$first_ip-cbcf::'"
+    );
+    is( $tickets->Count, 1, "found one ticket" );
+    is( $tickets->First->FirstCustomFieldValue('IP'), $first_ip, "correct value" );
+    $tickets = RT::Tickets->new( $RT::SystemUser );
+    $tickets->FromSQL(
+        "(id = $id1 OR id = $id2) AND CF.{IP} = '$second_ip-cbdf::'");
+    is( $tickets->Count, 1, "found one ticket" );
+    is( $tickets->First->FirstCustomFieldValue('IP'), $second_ip, "correct value" );
+
+    # IP range, with start IP greater than end
+    $tickets = RT::Tickets->new( $RT::SystemUser );
+    $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} =
+            'cbcf::-$first_ip'");
+    is( $tickets->Count, 1, "found one ticket" );
+    is( $tickets->First->FirstCustomFieldValue('IP'), $first_ip,, "correct value" );
+    $tickets = RT::Tickets->new( $RT::SystemUser );
+    $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = 'cbdf::-$second_ip'");
+    is( $tickets->Count, 1, "found one ticket" );
+    is( $tickets->First->FirstCustomFieldValue('IP'), $second_ip, "correct value" );
+
+    # CIDR/12
+    $tickets = RT::Tickets->new( $RT::SystemUser );
+    $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = 'cbcd::/12'");
+    is( $tickets->Count, 1, "found one ticket" );
+    is( $tickets->First->FirstCustomFieldValue('IP'), $first_ip, "correct value" );
+    $tickets = RT::Tickets->new( $RT::SystemUser );
+    $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = 'cbdd::/12'");
+    is( $tickets->Count, 1, "found one ticket" );
+    is( $tickets->First->FirstCustomFieldValue('IP'), $second_ip, "correct value" );
+
+    # IP is not in CIDR/24
+    $tickets = RT::Tickets->new( $RT::SystemUser );
+    $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} != 'cbcd::/12'");
+    is( $tickets->Count, 1, "found one ticket" );
+    is( $tickets->First->FirstCustomFieldValue('IP'), $second_ip,, "correct value" );
+    $tickets = RT::Tickets->new( $RT::SystemUser );
+    $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} != 'cbdd::/12'");
+    is( $tickets->Count, 1, "found one ticket" );
+    is( $tickets->First->FirstCustomFieldValue('IP'), $first_ip, "correct value" );
+
+    # CIDR or CIDR
+    $tickets = RT::Tickets->new( $RT::SystemUser );
+    $tickets->FromSQL("(id = $id1 OR id = $id2) AND "
+        ."(CF.{IP} = 'cbcd::/12' OR CF.{IP} = 'cbdd::/12')");
+    is( $tickets->Count, 2, "found both tickets" );
+}
+
+diag "create two tickets with different IP ranges and check several searches" if $ENV{'TEST_VERBOSE'};
+{
+    ok $agent->goto_create_ticket($q), "go to create ticket";
+    my $cf_field = "Object-RT::Ticket--CustomField-$cf_id-Values";
+    $agent->submit_form(
+        form_name => 'TicketCreate',
+        fields    => {
+            Subject   => 'test ip',
+            $cf_field => 'ddcd::/16',
+        }
+    );
+
+    my ($id1) = $agent->content =~ /Ticket (\d+) created/;
+    ok( $id1, "created first ticket $id1" );
+
+    ok $agent->goto_create_ticket($q), "go to create ticket";
+    $agent->submit_form(
+        form_name => 'TicketCreate',
+        fields    => {
+            Subject   => 'test ip',
+            $cf_field => 'edcd::/16',
+        }
+    );
+
+    my ($id2) = $agent->content =~ /Ticket (\d+) created/;
+    ok( $id2, "created ticket $id2" );
+
+    my $tickets = RT::Tickets->new( $RT::SystemUser );
+    $tickets->FromSQL("id = $id1 OR id = $id2");
+    is( $tickets->Count, 2, "found both tickets by 'id = x OR y'" );
+
+    # IP
+    $tickets = RT::Tickets->new( $RT::SystemUser );
+    $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = 'ddcd::'");
+    is( $tickets->Count, 1, "found one ticket" );
+    is( $tickets->First->id, $id1, "correct value" );
+    $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = 'ddcd:abcd::'");
+    is( $tickets->Count, 1, "found one ticket" );
+    is( $tickets->First->id, $id1, "correct value" );
+    $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = 'ddcd:ffff::'");
+    is( $tickets->Count, 1, "found one ticket" );
+    is( $tickets->First->id, $id1, "correct value" );
+    $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = 'edcd::abcd'");
+    is( $tickets->Count, 1, "found one ticket" );
+    is( $tickets->First->id, $id2, "correct value" );
+    $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = 'edcd::ffff'");
+    is( $tickets->Count, 1, "found one ticket" );
+    is( $tickets->First->id, $id2, "correct value" );
+    $tickets->FromSQL(
+"(id = $id1 OR id = $id2) AND CF.{IP} = 'edcd:ffff:ffff:ffff:ffff:ffff:ffff:ffff'"
+    );
+    is( $tickets->Count, 1, "found one ticket" );
+    is( $tickets->First->id, $id2, "correct value" );
+
+    # IP/32 - one address
+    $tickets = RT::Tickets->new( $RT::SystemUser );
+    $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = 'ddcd::/32'");
+    is( $tickets->Count, 1, "found one ticket" );
+    is( $tickets->First->id, $id1, "correct value" );
+    $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = 'edcd::/32'");
+    is( $tickets->Count, 1, "found one ticket" );
+    is( $tickets->First->id, $id2, "correct value" );
+
+    # IP range, lower than both
+    $tickets = RT::Tickets->new( $RT::SystemUser );
+    $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = 'abcd::/32'");
+    is( $tickets->Count, 0, "didn't finnd ticket" ) or diag "but found ". $tickets->First->id;
+
+    # IP range, intersect with the first range
+    $tickets->FromSQL(
+        "(id = $id1 OR id = $id2) AND CF.{IP} = 'ddcc::-ddcd:ab::'"
+    );
+    is( $tickets->Count, 1, "found one ticket" );
+    is( $tickets->First->id, $id1, "correct value" );
+
+    # IP range, equal to the first range
+    $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = 'ddcd::/16'");
+    is( $tickets->Count, 1, "found one ticket" );
+    is( $tickets->First->id, $id1, "correct value" );
+
+    # IP range, lay inside the first range
+    $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = 'ddcd:ab::'");
+    is( $tickets->Count, 1, "found one ticket" );
+    is( $tickets->First->id, $id1, "correct value" );
+
+    # IP range, intersect with the ranges
+    $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = 'ddcc::-edcd:ab::'");
+    is( $tickets->Count, 2, "found both tickets" );
+
+    # IP range, equal to range from the starting IP of the first ticket to the ending IP of the second
+    $tickets->FromSQL(
+        "(id = $id1 OR id = $id2) AND CF.{IP} = 'ddcd::-edcd:ffff:ffff:ffff:ffff:ffff:ffff:ffff'"
+    );
+    is( $tickets->Count, 2, "found both tickets" );
+
+    # IP range, has the both ranges inside it
+    $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = 'd000::/2'");
+    is( $tickets->Count, 2, "found both tickets" );
+
+    # IP range, greater than both
+    $tickets = RT::Tickets->new( $RT::SystemUser );
+    $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = 'ffff::/16'");
+    is( $tickets->Count, 0, "didn't find ticket" ) or diag "but found ". $tickets->First->id;
+}
+
+

-----------------------------------------------------------------------


More information about the Rt-commit mailing list