first pass RT4 merge, RT#13852
[freeside.git] / rt / t / customfields / iprange.t
1 #!/usr/bin/perl
2
3 use strict;
4 use warnings;
5
6 use RT::Test tests => 133;
7
8 my ($baseurl, $agent) =RT::Test->started_ok;
9 ok( $agent->login, 'log in' );
10
11 my $q = RT::Queue->new($RT::SystemUser);
12 $q->Load('General');
13 my $ip_cf = RT::CustomField->new($RT::SystemUser);
14         
15 my ($val,$msg) = $ip_cf->Create(Name => 'IP', Type =>'IPAddressRange', LookupType => 'RT::Queue-RT::Ticket');
16 ok($val,$msg);
17 my $cf_id = $val;
18 $ip_cf->AddToObject($q);
19 use_ok('RT');
20
21 my $cf;
22 diag "load and check basic properties of the IP CF" if $ENV{'TEST_VERBOSE'};
23 {
24     my $cfs = RT::CustomFields->new( $RT::SystemUser );
25     $cfs->Limit( FIELD => 'Name', VALUE => 'IP' );
26     is( $cfs->Count, 1, "found one CF with name 'IP'" );
27
28     $cf = $cfs->First;
29     is( $cf->Type, 'IPAddressRange', 'type check' );
30     is( $cf->LookupType, 'RT::Queue-RT::Ticket', 'lookup type check' );
31     ok( !$cf->MaxValues, "unlimited number of values" );
32     ok( !$cf->Disabled, "not disabled" );
33 }
34
35 diag "check that CF applies to queue General" if $ENV{'TEST_VERBOSE'};
36 {
37     my $cfs = $q->TicketCustomFields;
38     $cfs->Limit( FIELD => 'id', VALUE => $cf->id, ENTRYAGGREGATOR => 'AND' );
39     is( $cfs->Count, 1, 'field applies to queue' );
40 }
41
42 diag "create a ticket via web and set IP" if $ENV{'TEST_VERBOSE'};
43 {
44     my $val = '192.168.20.1';
45     ok $agent->goto_create_ticket($q), "go to create ticket";
46     my $cf_field = "Object-RT::Ticket--CustomField-$cf_id-Values";
47     $agent->submit_form(
48         form_name => 'TicketCreate',
49         fields    => {
50             Subject                                       => 'test ip',
51             $cf_field => $val,
52         }
53     );
54
55     $agent->content_like( qr/\Q$val/, "IP on the page" );
56     my ($id) = $agent->content =~ /Ticket (\d+) created/;
57     ok( $id, "created ticket $id" );
58
59     my $ticket = RT::Ticket->new($RT::SystemUser);
60     $ticket->Load($id);
61     ok( $ticket->id, 'loaded ticket' );
62     is( $ticket->FirstCustomFieldValue('IP'), $val, 'correct value' );
63 }
64
65 diag "create a ticket via web with CIDR" if $ENV{'TEST_VERBOSE'};
66 {
67     my $val = '172.16.20/31';
68     ok $agent->goto_create_ticket($q), "go to create ticket";
69     my $cf_field = "Object-RT::Ticket--CustomField-$cf_id-Values";
70     $agent->submit_form(
71         form_name => 'TicketCreate',
72         fields    => {
73             Subject                                       => 'test ip',
74             $cf_field => $val,
75         }
76     );
77
78     my ($id) = $agent->content =~ /Ticket (\d+) created/;
79     ok( $id, "created ticket $id" );
80
81     my $ticket = RT::Ticket->new($RT::SystemUser);
82     $ticket->Load($id);
83     ok( $ticket->id, 'loaded ticket' );
84     is( $ticket->FirstCustomFieldValue('IP'), '172.16.20.0-172.16.20.1', 'correct value' );
85 }
86
87 diag "create a ticket and edit IP field using Edit page" if $ENV{'TEST_VERBOSE'};
88 {
89     my $val = '172.16.0.1';
90     ok $agent->goto_create_ticket($q), "go to create ticket";
91     $agent->submit_form(
92         form_name => 'TicketCreate',
93         fields    => { Subject => 'test ip', }
94     );
95
96     my ($id) = $agent->content =~ /Ticket (\d+) created/;
97     ok( $id, "created ticket $id" );
98     my $cf_field = "Object-RT::Ticket-$id-CustomField-$cf_id-Values";
99
100     $agent->follow_link_ok( { text => 'Basics', n => "1" },
101         "Followed 'Basics' link" );
102     $agent->form_name('TicketModify');
103
104     like( $agent->value($cf_field), qr/^\s*$/, 'IP is empty' );
105     $agent->field( $cf_field => $val );
106     $agent->click('SubmitTicket');
107
108     $agent->content_like( qr/\Q$val/, "IP on the page" );
109
110     my $ticket = RT::Ticket->new($RT::SystemUser);
111     $ticket->Load($id);
112     ok( $ticket->id, 'loaded ticket' );
113     is( $ticket->FirstCustomFieldValue('IP'), $val, 'correct value' );
114
115     diag "set IP with spaces around" if $ENV{'TEST_VERBOSE'};
116     $val = "  172.16.0.2  \n  ";
117     $agent->follow_link_ok( { text => 'Basics', n => "1" },
118         "Followed 'Basics' link" );
119     $agent->form_name('TicketModify');
120     like( $agent->value($cf_field),
121         qr/^\s*\Q172.16.0.1\E\s*$/, 'IP is in input box' );
122     $agent->field( $cf_field => $val );
123     $agent->click('SubmitTicket');
124
125     $agent->content_like( qr/\Q172.16.0.2/, "IP on the page" );
126
127     $ticket = RT::Ticket->new($RT::SystemUser);
128     $ticket->Load($id);
129     ok( $ticket->id, 'loaded ticket' );
130     is( $ticket->FirstCustomFieldValue('IP'), '172.16.0.2', 'correct value' );
131
132     diag "replace IP with a range" if $ENV{'TEST_VERBOSE'};
133     $val = '172.16.0.0-172.16.0.255';
134     $agent->follow_link_ok( { text => 'Basics', n => "1" },
135         "Followed 'Basics' link" );
136     $agent->form_name('TicketModify');
137     like( $agent->value($cf_field),
138         qr/^\s*\Q172.16.0.2\E\s*$/, 'IP is in input box' );
139     $agent->field( $cf_field => $val );
140     $agent->click('SubmitTicket');
141
142     $agent->content_like( qr/\Q$val/, "IP on the page" );
143
144     $ticket = RT::Ticket->new($RT::SystemUser);
145     $ticket->Load($id);
146     ok( $ticket->id, 'loaded ticket' );
147     is( $ticket->FirstCustomFieldValue('IP'), $val, 'correct value' );
148
149     diag "delete range, add another range using CIDR" if $ENV{'TEST_VERBOSE'};
150     $val = '172.16/16';
151     $agent->follow_link_ok( { text => 'Basics', n => "1" },
152         "Followed 'Basics' link" );
153     $agent->form_name('TicketModify');
154     is( $agent->value($cf_field),
155         '172.16.0.0-172.16.0.255', 'IP is in input box' );
156     $agent->field( $cf_field => $val );
157     $agent->click('SubmitTicket');
158
159     $agent->content_like( qr/\Q$val/, "IP on the page" );
160
161     $ticket = RT::Ticket->new($RT::SystemUser);
162     $ticket->Load($id);
163     ok( $ticket->id, 'loaded ticket' );
164     is( $ticket->FirstCustomFieldValue('IP'),
165         '172.16.0.0-172.16.255.255', 'correct value' );
166 }
167
168 diag "check that we parse correct IPs only" if $ENV{'TEST_VERBOSE'};
169 {
170
171     my $cf_field = "Object-RT::Ticket--CustomField-$cf_id-Values";
172     for my $valid (qw/1.0.0.0 255.255.255.255/) {
173         ok $agent->goto_create_ticket($q), "go to create ticket";
174         $agent->submit_form(
175             form_name => 'TicketCreate',
176             fields    => {
177                 Subject   => 'test ip',
178                 $cf_field => $valid,
179             }
180         );
181
182         my ($id) = $agent->content =~ /Ticket (\d+) created/;
183         ok( $id, "created ticket $id" );
184         my $ticket = RT::Ticket->new($RT::SystemUser);
185         $ticket->Load($id);
186         is( $ticket->id, $id, 'loaded ticket' );
187
188         is( $ticket->FirstCustomFieldValue('IP'), $valid, 'correct value' );
189     }
190
191     for my $invalid (qw{255.255.255.256 355.255.255.255 8.13.8/8.13.0/1.0}) {
192         ok $agent->goto_create_ticket($q), "go to create ticket";
193         $agent->submit_form(
194             form_name => 'TicketCreate',
195             fields    => {
196                 Subject   => 'test ip',
197                 $cf_field => $invalid,
198             }
199         );
200
201         $agent->content_like( qr/can not be parsed as an IP address range/, 'ticket fails to create' );
202     }
203
204 }
205
206 diag "search tickets by IP" if $ENV{'TEST_VERBOSE'};
207 {
208     my $val = '172.16.1/31';
209     ok $agent->goto_create_ticket($q), "go to create ticket";
210     my $cf_field = "Object-RT::Ticket--CustomField-$cf_id-Values";
211     $agent->submit_form(
212         form_name => 'TicketCreate',
213         fields    => {
214             Subject   => 'test ip',
215             $cf_field => $val,
216         }
217     );
218
219     my ($id) = $agent->content =~ /Ticket (\d+) created/;
220     ok( $id, "created ticket $id" );
221
222     my $ticket = RT::Ticket->new($RT::SystemUser);
223     $ticket->Load($id);
224     ok( $ticket->id, 'loaded ticket' );
225
226     my $tickets = RT::Tickets->new($RT::SystemUser);
227     $tickets->FromSQL("id = $id AND CF.{IP} = '172.16.1.1'");
228     ok( $tickets->Count, "found tickets" );
229
230     is( $ticket->FirstCustomFieldValue('IP'),
231         '172.16.1.0-172.16.1.1', 'correct value' );
232 }
233
234 diag "search tickets by IP range" if $ENV{'TEST_VERBOSE'};
235 {
236     my $val = '172.16.2/26';
237     ok $agent->goto_create_ticket($q), "go to create ticket";
238     my $cf_field = "Object-RT::Ticket--CustomField-$cf_id-Values";
239     $agent->submit_form(
240         form_name => 'TicketCreate',
241         fields    => {
242             Subject   => 'test ip',
243             $cf_field => $val,
244         }
245     );
246
247     my ($id) = $agent->content =~ /Ticket (\d+) created/;
248     ok( $id, "created ticket $id" );
249
250     my $ticket = RT::Ticket->new($RT::SystemUser);
251     $ticket->Load($id);
252     ok( $ticket->id, 'loaded ticket' );
253
254     my $tickets = RT::Tickets->new( $RT::SystemUser );
255     $tickets->FromSQL("id = $id AND CF.{IP} = '172.16.2.0-172.16.2.255'");
256     ok( $tickets->Count, "found tickets" );
257
258     is( $ticket->FirstCustomFieldValue('IP'),
259         '172.16.2.0-172.16.2.63', 'correct value' );
260 }
261
262 diag "create two tickets with different IPs and check several searches" if $ENV{'TEST_VERBOSE'};
263 {
264     ok $agent->goto_create_ticket($q), "go to create ticket";
265     my $cf_field = "Object-RT::Ticket--CustomField-$cf_id-Values";
266     $agent->submit_form(
267         form_name => 'TicketCreate',
268         fields    => {
269             Subject   => 'test ip',
270             $cf_field => '192.168.21.10',
271         }
272     );
273
274     my ($id1) = $agent->content =~ /Ticket (\d+) created/;
275     ok( $id1, "created first ticket $id1" );
276
277     ok $agent->goto_create_ticket($q), "go to create ticket";
278     $agent->submit_form(
279         form_name => 'TicketCreate',
280         fields    => {
281             Subject   => 'test ip',
282             $cf_field => '192.168.22.10',
283         }
284     );
285
286     my ($id2) = $agent->content =~ /Ticket (\d+) created/;
287     ok( $id2, "created second ticket $id2" );
288
289     my $tickets = RT::Tickets->new( $RT::SystemUser );
290     $tickets->FromSQL("id = $id1 OR id = $id2");
291     is( $tickets->Count, 2, "found both tickets by 'id = x OR y'" );
292
293     # IP
294     $tickets = RT::Tickets->new( $RT::SystemUser );
295     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = '192.168.21.10'");
296     is( $tickets->Count, 1, "found one ticket" );
297     is( $tickets->First->FirstCustomFieldValue('IP'), '192.168.21.10', "correct value" );
298     $tickets = RT::Tickets->new( $RT::SystemUser );
299     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = '192.168.22.10'");
300     is( $tickets->Count, 1, "found one ticket" );
301     is( $tickets->First->FirstCustomFieldValue('IP'), '192.168.22.10', "correct value" );
302
303     # IP/32 - one address
304     $tickets = RT::Tickets->new( $RT::SystemUser );
305     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = '192.168.21.10/32'");
306     is( $tickets->Count, 1, "found one ticket" );
307     is( $tickets->First->FirstCustomFieldValue('IP'), '192.168.21.10', "correct value" );
308     $tickets = RT::Tickets->new( $RT::SystemUser );
309     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = '192.168.22.10/32'");
310     is( $tickets->Count, 1, "found one ticket" );
311     is( $tickets->First->FirstCustomFieldValue('IP'), '192.168.22.10', "correct value" );
312
313     # IP range
314     $tickets = RT::Tickets->new( $RT::SystemUser );
315     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = '192.168.21.0-192.168.21.255'");
316     is( $tickets->Count, 1, "found one ticket" );
317     is( $tickets->First->FirstCustomFieldValue('IP'), '192.168.21.10', "correct value" );
318     $tickets = RT::Tickets->new( $RT::SystemUser );
319     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = '192.168.22.0-192.168.22.255'");
320     is( $tickets->Count, 1, "found one ticket" );
321     is( $tickets->First->FirstCustomFieldValue('IP'), '192.168.22.10', "correct value" );
322
323     # IP range, with start IP greater than end
324     $tickets = RT::Tickets->new( $RT::SystemUser );
325     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = '192.168.21.255-192.168.21.0'");
326     is( $tickets->Count, 1, "found one ticket" );
327     is( $tickets->First->FirstCustomFieldValue('IP'), '192.168.21.10', "correct value" );
328     $tickets = RT::Tickets->new( $RT::SystemUser );
329     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = '192.168.22.255-192.168.22.0'");
330     is( $tickets->Count, 1, "found one ticket" );
331     is( $tickets->First->FirstCustomFieldValue('IP'), '192.168.22.10', "correct value" );
332
333     # CIDR/24
334     $tickets = RT::Tickets->new( $RT::SystemUser );
335     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = '192.168.21.0/24'");
336     is( $tickets->Count, 1, "found one ticket" );
337     is( $tickets->First->FirstCustomFieldValue('IP'), '192.168.21.10', "correct value" );
338     $tickets = RT::Tickets->new( $RT::SystemUser );
339     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = '192.168.22.0/24'");
340     is( $tickets->Count, 1, "found one ticket" );
341     is( $tickets->First->FirstCustomFieldValue('IP'), '192.168.22.10', "correct value" );
342
343     # IP is not in CIDR/24
344     $tickets = RT::Tickets->new( $RT::SystemUser );
345     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} != '192.168.21.0/24'");
346     is( $tickets->Count, 1, "found one ticket" );
347     is( $tickets->First->FirstCustomFieldValue('IP'), '192.168.22.10', "correct value" );
348     $tickets = RT::Tickets->new( $RT::SystemUser );
349     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} != '192.168.22.0/24'");
350     is( $tickets->Count, 1, "found one ticket" );
351     is( $tickets->First->FirstCustomFieldValue('IP'), '192.168.21.10', "correct value" );
352
353     # CIDR or CIDR
354     $tickets = RT::Tickets->new( $RT::SystemUser );
355     $tickets->FromSQL("(id = $id1 OR id = $id2) AND "
356         ."(CF.{IP} = '192.168.21.0/24' OR CF.{IP} = '192.168.22.0/24')");
357     is( $tickets->Count, 2, "found both tickets" );
358 }
359
360 diag "create two tickets with different IP ranges and check several searches" if $ENV{'TEST_VERBOSE'};
361 {
362     ok $agent->goto_create_ticket($q), "go to create ticket";
363     my $cf_field = "Object-RT::Ticket--CustomField-$cf_id-Values";
364     $agent->submit_form(
365         form_name => 'TicketCreate',
366         fields    => {
367             Subject   => 'test ip',
368             $cf_field => '192.168.21.0-192.168.21.127',
369         }
370     );
371
372     my ($id1) = $agent->content =~ /Ticket (\d+) created/;
373     ok( $id1, "created first ticket $id1" );
374
375     ok $agent->goto_create_ticket($q), "go to create ticket";
376     $agent->submit_form(
377         form_name => 'TicketCreate',
378         fields    => {
379             Subject   => 'test ip',
380             $cf_field => '192.168.21.128-192.168.21.255',
381         }
382     );
383
384     my ($id2) = $agent->content =~ /Ticket (\d+) created/;
385     ok( $id2, "created ticket $id2" );
386
387     my $tickets = RT::Tickets->new( $RT::SystemUser );
388     $tickets->FromSQL("id = $id1 OR id = $id2");
389     is( $tickets->Count, 2, "found both tickets by 'id = x OR y'" );
390
391     # IP
392     $tickets = RT::Tickets->new( $RT::SystemUser );
393     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = '192.168.21.0'");
394     is( $tickets->Count, 1, "found one ticket" );
395     is( $tickets->First->id, $id1, "correct value" );
396     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = '192.168.21.64'");
397     is( $tickets->Count, 1, "found one ticket" );
398     is( $tickets->First->id, $id1, "correct value" );
399     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = '192.168.21.127'");
400     is( $tickets->Count, 1, "found one ticket" );
401     is( $tickets->First->id, $id1, "correct value" );
402     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = '192.168.21.128'");
403     is( $tickets->Count, 1, "found one ticket" );
404     is( $tickets->First->id, $id2, "correct value" );
405     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = '192.168.21.191'");
406     is( $tickets->Count, 1, "found one ticket" );
407     is( $tickets->First->id, $id2, "correct value" );
408     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = '192.168.21.255'");
409     is( $tickets->Count, 1, "found one ticket" );
410     is( $tickets->First->id, $id2, "correct value" );
411
412     # IP/32 - one address
413     $tickets = RT::Tickets->new( $RT::SystemUser );
414     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = '192.168.21.63/32'");
415     is( $tickets->Count, 1, "found one ticket" );
416     is( $tickets->First->id, $id1, "correct value" );
417     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = '192.168.21.191/32'");
418     is( $tickets->Count, 1, "found one ticket" );
419     is( $tickets->First->id, $id2, "correct value" );
420
421     # IP range, lower than both
422     $tickets = RT::Tickets->new( $RT::SystemUser );
423     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = '192.168.20.0-192.168.20.255'");
424     is( $tickets->Count, 0, "didn't finnd ticket" ) or diag "but found ". $tickets->First->id;
425
426     # IP range, intersect with the first range
427     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = '192.168.20.0-192.168.21.63'");
428     is( $tickets->Count, 1, "found one ticket" );
429     is( $tickets->First->id, $id1, "correct value" );
430
431     # IP range, equal to the first range
432     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = '192.168.21.0-192.168.21.127'");
433     is( $tickets->Count, 1, "found one ticket" );
434     is( $tickets->First->id, $id1, "correct value" );
435
436     # IP range, lay inside the first range
437     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = '192.168.21.31-192.168.21.63'");
438     is( $tickets->Count, 1, "found one ticket" );
439     is( $tickets->First->id, $id1, "correct value" );
440
441     # IP range, intersect with the ranges
442     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = '192.168.21.31-192.168.21.191'");
443     is( $tickets->Count, 2, "found both tickets" );
444
445     # IP range, equal to range from the starting IP of the first ticket to the ending IP of the second
446     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = '192.168.21.0-192.168.21.255'");
447     is( $tickets->Count, 2, "found both tickets" );
448
449     # IP range, has the both ranges inside it
450     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = '192.168/16'");
451     is( $tickets->Count, 2, "found both tickets" );
452
453     # IP range, greater than both
454     $tickets = RT::Tickets->new( $RT::SystemUser );
455     $tickets->FromSQL("(id = $id1 OR id = $id2) AND CF.{IP} = '192.168.22/24'");
456     is( $tickets->Count, 0, "didn't find ticket" ) or diag "but found ". $tickets->First->id;
457 }
458
459
460 diag "test the operators in search page" if $ENV{'TEST_VERBOSE'};
461 {
462     $agent->get_ok( $baseurl . "/Search/Build.html?Query=Queue='General'" );
463     $agent->content_contains('CF.{IP}', 'got CF.{IP}');
464     my $form = $agent->form_name('BuildQuery');
465     my $op = $form->find_input("'CF.{IP}'Op");
466     ok( $op, "found 'CF.{IP}'Op" );
467     is_deeply( [ $op->possible_values ], [ '=', '!=', '<', '>' ], 'op values' );
468 }
469