rt 4.0.23
[freeside.git] / rt / t / fts / indexed_pg.t
1
2 use strict;
3 use warnings;
4
5 use RT::Test tests => undef;
6 plan skip_all => 'Not Pg' unless RT->Config->Get('DatabaseType') eq 'Pg';
7
8 my ($major, $minor) = $RT::Handle->dbh->get_info(18) =~ /^0*(\d+)\.0*(\d+)/;
9 plan skip_all => "Need Pg 8.2 or higher; we have $major.$minor"
10     if "$major.$minor" < 8.2;
11
12 RT->Config->Set( FullTextSearch => Enable => 1, Indexed => 1, Column => 'ContentIndex', Table => 'Attachments' );
13
14 setup_indexing();
15
16 my $q = RT::Test->load_or_create_queue( Name => 'General' );
17 ok $q && $q->id, 'loaded or created queue';
18 my $queue = $q->Name;
19
20 sub setup_indexing {
21     my %args = (
22         'no-ask'       => 1,
23         command        => $RT::SbinPath .'/rt-setup-fulltext-index',
24         dba            => $ENV{'RT_DBA_USER'},
25         'dba-password' => $ENV{'RT_DBA_PASSWORD'},
26     );
27     my ($exit_code, $output) = RT::Test->run_and_capture( %args );
28     ok(!$exit_code, "setted up index") or diag "output: $output";
29 }
30
31 sub sync_index {
32     my %args = (
33         command => $RT::SbinPath .'/rt-fulltext-indexer',
34     );
35     my ($exit_code, $output) = RT::Test->run_and_capture( %args );
36     ok(!$exit_code, "setted up index") or diag "output: $output";
37 }
38
39 sub run_tests {
40     my @test = @_;
41     while ( my ($query, $checks) = splice @test, 0, 2 ) {
42         run_test( $query, %$checks );
43     }
44 }
45
46 my @tickets;
47 sub run_test {
48     my ($query, %checks) = @_;
49     my $query_prefix = join ' OR ', map 'id = '. $_->id, @tickets;
50
51     my $tix = RT::Tickets->new(RT->SystemUser);
52     $tix->FromSQL( "( $query_prefix ) AND ( $query )" );
53
54     my $error = 0;
55
56     my $count = 0;
57     $count++ foreach grep $_, values %checks;
58     is($tix->Count, $count, "found correct number of ticket(s) by '$query'") or $error = 1;
59
60     my $good_tickets = ($tix->Count == $count);
61     while ( my $ticket = $tix->Next ) {
62         next if $checks{ $ticket->id };
63         diag $ticket->Subject ." ticket has been found when it's not expected";
64         $good_tickets = 0;
65     }
66     ok( $good_tickets, "all tickets are good with '$query'" ) or $error = 1;
67
68     diag "Wrong SQL query for '$query':". $tix->BuildSelectQuery if $error;
69 }
70
71 my $blase = Encode::decode_utf8("blasé");
72 @tickets = RT::Test->create_tickets(
73     { Queue => $q->id },
74     { Subject => 'fts test 1', Content => "book $blase" },
75     { Subject => 'fts test 2', Content => "bars blas&eacute;", ContentType => 'text/html'  },
76 );
77 sync_index();
78
79 my $book = $tickets[0];
80 my $bars = $tickets[1];
81
82 run_tests(
83     "Content LIKE 'book'" => { $book->id => 1, $bars->id => 0 },
84     "Content LIKE 'bars'" => { $book->id => 0, $bars->id => 1 },
85
86     # Unicode searching
87     "Content LIKE '$blase'" => { $book->id => 1, $bars->id => 1 },
88     "Content LIKE 'blase'"  => { $book->id => 0, $bars->id => 0 },
89     "Content LIKE 'blas'"   => { $book->id => 0, $bars->id => 0 },
90
91     # make sure that Pg stemming works
92     "Content LIKE 'books'" => { $book->id => 1, $bars->id => 0 },
93     "Content LIKE 'bar'"   => { $book->id => 0, $bars->id => 1 },
94
95     # no matches
96     "Content LIKE 'baby'" => { $book->id => 0, $bars->id => 0 },
97     "Content LIKE 'pubs'" => { $book->id => 0, $bars->id => 0 },
98 );
99
100 # Test the "ts_vector too long" skip
101 my $content = "";
102 $content .= "$_\n" for 1..200_000;
103 @tickets = RT::Test->create_tickets(
104     { Queue => $q->id },
105     { Subject => 'Short content', Content => '50' },
106     { Subject => 'Long content',  Content => $content  },
107     { Subject => 'More short',    Content => '50' },
108 );
109
110 my ($exit_code, $output) = RT::Test->run_and_capture(
111     command => $RT::SbinPath .'/rt-fulltext-indexer'
112 );
113 like($output, qr/string is too long for tsvector/, "Got a warning for the ticket");
114 ok(!$exit_code, "set up index");
115
116 # The long content is skipped entirely
117 run_tests(
118     "Content LIKE '1'"  => { $tickets[0]->id => 0, $tickets[1]->id => 0, $tickets[2]->id => 0 },
119     "Content LIKE '50'" => { $tickets[0]->id => 1, $tickets[1]->id => 0, $tickets[2]->id => 1 },
120 );
121
122 @tickets = ();
123
124 done_testing;